//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#include <ddk.h>
#include <bulverde.h>
#include <drvpub.h>
#include "display_def.h"

const unsigned int Samsung_LTP283QV_InitParaList[][3] =
{
#if 1

	{0x0007, 0x0000, 0},
	{0x0012, 0x0000, 10},

      //
	{0x0011, 0x000b, 0},
	{0x0012, 0x081d, 0},
	{0x0013, 0x0027, 0},
	{0x0014, 0x0000, 0},
	{0x0010, 0x3104, 0},
	{0x0011, 0x0449, 50},

       //
	{0x0007, 0x0009, 0},
	{0x0012, 0x085c, 200},

	//
	{0x0001, 0x7127, 0},
	{0x0002, 0x0300, 0},
	{0x0003, 0x5000, 0},
	{0x0008, 0x0008, 0},
	{0x000b, 0x2a00, 0},
	{0x000c, 0x0000, 0},
	{0x000d, 0x0004, 0},
	{0x0015, 0x0018, 0},
	{0x0016, 0x0018, 0},
	{0x0017, 0x0001, 0},
	{0x0030, 0x0307, 0},
	{0x0031, 0x0204, 0},
	{0x0032, 0x0002, 0},
	{0x0033, 0x0405, 0},
	{0x0034, 0x0007, 0},
	{0x0035, 0x0002, 0},
	{0x0036, 0x0204, 0},
	{0x0037, 0x0606, 0},
	{0x0038, 0x0606, 0},
	{0x0039, 0x1f00, 0},
	{0x0070, 0x0001, 0},
	{0x0075, 0x0000, 0},
	{0x0007, 0x0009, 40},
	//
	{0x0007, 0x0049, 40},
	{0x0007, 0x004b, 40},
#endif
    //end
};
#define LTP283QV_F03_INIT_PARA_NUM (sizeof(Samsung_LTP283QV_InitParaList)/sizeof(unsigned int)/3)

#define GPIO_LCDPOWER   82
#define GPIO_LCDCS      94
#define GPIO_LCDSCLK    95
#define GPIO_LCDSI      96
#define GPIO_LCDRSB     77
#define GPIO_LCDRESET   107

INLINE void DelayMs(int ms)
{
    DzDelay(1000 * ms);
}

INLINE void DelayUs(int us)
{
    DzDelay(us);
}

INLINE void LCD_PWR(UINT8 Lv)
{
    if (Lv)
    {
        Gpio_SetOutHigh(GPIO_LCDPOWER);
    }
    else
    {
        Gpio_SetOutLow(GPIO_LCDPOWER);
    }
}

INLINE void LCD_CS(UINT8 Lv)
{
    if (Lv)
    {
        Gpio_SetOutHigh(GPIO_LCDCS);
    }
    else
    {
        Gpio_SetOutLow(GPIO_LCDCS);
    }
}

INLINE void LCD_SCL(UINT8 Lv)
{
    if (Lv)
    {
        Gpio_SetOutHigh(GPIO_LCDSCLK);
    }
    else
    {
        Gpio_SetOutLow(GPIO_LCDSCLK);
    }
}

INLINE void LCD_SI(UINT8 Lv)
{
    if (Lv)
    {
        Gpio_SetOutHigh(GPIO_LCDSI);
    }
    else
    {
        Gpio_SetOutLow(GPIO_LCDSI);
    }
}

INLINE void LCD_RSB(UINT8 Lv)
{
    if (Lv)
    {
        Gpio_SetOutHigh(GPIO_LCDRSB);
    }
    else
    {
        Gpio_SetOutLow(GPIO_LCDRSB);
    }
}

INLINE void LCD_RST(UINT8 Lv)
{
    if (Lv)
    {
        Gpio_SetOutHigh(GPIO_LCDRESET);
    }
    else
    {
        Gpio_SetOutLow(GPIO_LCDRESET);
    }
}

//
//Don't need to change it for paladin TD
void LcdSend(UINT32 Cmd, UINT32 Value)
{
	UINT32	Shift;
	UINT32	Cnt;
	UINT32	Idex = 0x74;
	UINT32	Data = 0x76;

    // pull up CS
	LCD_CS(1);
    // pull up SCL
    LCD_SCL(1);
	DelayUs(20);
    // pull donw CS
	LCD_CS(0);

	// index
	LCD_RSB(0);
	Shift = 0x80;

	for (Cnt = 0; Cnt < 8; Cnt++)
	{
		if (Idex & Shift)
		{
			LCD_SI(1);
		}
		else
		{
			LCD_SI(0);
		}
		Shift = Shift >> 1;
		DelayUs(2);
		LCD_SCL(0);
		DelayUs(1);
		LCD_SCL(1);
		DelayUs(1);
	}

	/*write the register address*/
	Shift = 0x8000;
	for (Cnt = 0; Cnt < 16; Cnt++)
	{
		if (Cmd&Shift)
		{
			LCD_SI(1);
		}
		else
		{
			LCD_SI(0);
		}
		Shift = Shift >> 1;
		DelayUs(2);
		LCD_SCL(0);
		DelayUs(1);
		LCD_SCL(1);
		DelayUs(1);
	}

	LCD_CS(1);
	DelayUs(8);
	LCD_RSB(1);
	LCD_CS(0);
	Shift = 0x80;
	for (Cnt = 0; Cnt < 8; Cnt++)
	{
		if (Data&Shift)
		{
			LCD_SI(1);
		}
		else
		{
			LCD_SI(0);
		}
		Shift = Shift >> 1;
		DelayUs(2);
		LCD_SCL(0);
		DelayUs(1);
		LCD_SCL(1);
		DelayUs(1);
	}

	/*write register data*/
	Shift = 0x8000;
	for (Cnt = 0; Cnt < 16; Cnt++)
	{
		if (Value&Shift)
		{
			LCD_SI(1);
		}
		else
		{
			LCD_SI(0);
		}
		Shift=Shift>>1;
		DelayUs(4);
		LCD_SCL(0);
		DelayUs(2);
		LCD_SCL(1);
		DelayUs(2);
	}
	LCD_CS(1);
}

void InitLcd()
{
    unsigned int i;

    // Power on LCD
    LCD_PWR(1);
    // Reset LCD
    LCD_RST(0);
    DelayMs(50);
    LCD_RST(1);
    DelayMs(10);

    // Set LCD Parameters
    for (i = 0; i < LTP283QV_F03_INIT_PARA_NUM; i++)
    {
        LcdSend(Samsung_LTP283QV_InitParaList[i][0], Samsung_LTP283QV_InitParaList[i][1]); // cmd
        if (Samsung_LTP283QV_InitParaList[i][2] > 0)
            DelayMs(Samsung_LTP283QV_InitParaList[i][2]);
    }
    LCD_RSB(0);
}


///////////////////////////////////////////////////////////////////////////////

void Lcm_SetupGPIOs(DisplayContext *pCxt)
{
    //        configure processor pins
	//        Mux Pin         GPIO     Alt   Direction
	//        Digital PWB      82        0      O
	//        P_L_CS           94        0      O
	//        P_L_SCL          95        0      O
	//        P_L_SI           96        0      O
	//        P_RSB            77        0      O
	//        P_RST           107        0      O

	// Note: From document, Alt of P_RSB & P_RST should be 0;
	// But actually they are both 2.

    Gpio_SetDir(GPIO_LCDPOWER, GPIO_PIN_OUT);
    Gpio_SetDir(GPIO_LCDCS, GPIO_PIN_OUT);
    Gpio_SetDir(GPIO_LCDSCLK, GPIO_PIN_OUT);
    Gpio_SetDir(GPIO_LCDSI, GPIO_PIN_OUT);
    Gpio_SetDir(GPIO_LCDRSB, GPIO_PIN_OUT);
    Gpio_SetDir(GPIO_LCDRESET, GPIO_PIN_OUT);

    Gpio_SetOutLow(GPIO_LCDPOWER);
    Gpio_SetOutLow(GPIO_LCDCS);
    Gpio_SetOutLow(GPIO_LCDSCLK);
    Gpio_SetOutLow(GPIO_LCDSI);
    Gpio_SetOutLow(GPIO_LCDRSB);
    Gpio_SetOutLow(GPIO_LCDRESET);

    Gpio_SetAFR(GPIO_LCDPOWER, GPIO_AS_GPIO ); // 82
    Gpio_SetAFR(GPIO_LCDCS, GPIO_AS_GPIO ); // 94
    Gpio_SetAFR(GPIO_LCDSCLK, GPIO_AS_GPIO ); // 95
    Gpio_SetAFR(GPIO_LCDSI, GPIO_AS_GPIO ); // 96
    // GPIO_AS_AF2 has been set automatically below.
    // Gpio_SetAFR(GPIO_LCDRSB, GPIO_AS_AF2 ); // 77
    // Gpio_SetAFR(GPIO_LCDRESET, GPIO_AS_AF2 ); // 107

    // LCD Data output and clock ouput
    // GPIO63 -- 58
    GPDR1 |=  0xfc000000;
    GAFR1_U |= 0xaaa00000;
    // GPIO 64 --  76
    GPDR2 |= 0x00001fff;
    GAFR2_L |= 0x02aaaaaa;

	return;
}

void Lcm_DisplayOn(DisplayContext *pCxt)
{
    InitLcd();
}

void Lcm_DisplayOff(DisplayContext *pCxt)
{
    LCD_PWR(0);
}
